- /* sdfdpow.cpp by K.Tsuru */
- // funcion ID 3018 DARDIX, BRADIX(n > 0)
- /*********************************************************
- SDouble class x^n
- Provides x to the n-th power using Knuth's binary method.
- For n > 0 it allows to hand a SDecimal object x.
- *********************************************************/
- #ifndef SN_H
- #include "sn.h"
- #endif
- static const char* const func = "Dpow";
- SDouble Dpow(const SDouble& x, long n){
- if( (x.Type() == x.BIN_DEC) && (n < 0) ) x.SetError(x.RADIX_ERR, func, 3018);
- if(x.Sign(3018) == 0) return x;
- SDouble one(x.Type(), 0);
- one = 1.0;
-
- int ix;
- if((ix = x.IsOne()) != 0){ //|x| = 1.0
- if( (ix < 0) && (labs(n) & 1) ) one.ChangeSign(); // x = -1
- return one;
- }
- if(!n) return one;
- else if(n == 1L) return x;
- else if(n == -1L) return DReciprocal(x); // 1/x
-
- // Check the condition "x^n < DRADIX^DRADIXEXP_MAX"
- double expR = (double)n*x.NetRdxExp()/(double)DFIGURES; // exponent of result
- if(fabs(expR) > DRADIX_EXP_MAX){
- if(expR > 0) x.SetError(x.OVERFLOW_ERR, func, 3018);
- x.SetError(x.UNDERFLOW_ERR, func, -3018);
- return 0.0;
- }
-
- /*************************************************************************
- The methods for the calculation of x^n (n < 0).
- method 1:Firstly let y = 1/x, and evaluates y^|n|.
- method 2:Firstly y = x^|n|, and evaluates 1/y.
-
- When x has many figures both method have same speed. But about the accuracy
- the method 1 has an advantage because the error of reciprocal in last few
- figures is excluded by multiplication.
- When x has small figures the method 2 has an advantage in speed because
- x^|n| can be evaluated rapidly.But to get a finite decimal such as 1/(2^10)
- exactly a rounding off is necessary."DReciprocal" includes this procedure.
- In evaluating 3^(-100) the method 2 is faster about eight times.
- ***************************************************************************/
- long m = labs(n);
- SDouble y(one), z(x.Type(), 0);
- int retRecY = 0; // return 1/y ?
- if(n < 0){ // Type() != BIN_DEC
- if(x.Last() - x.First() <= 5u){
- retRecY = 1; z = x; //small figures
- } else z = DReciprocal(x); // 1/x
- }else z = x;
-
- while(y.Sign(3018)){
- if(m % 2) y *= z;
- m /= 2;
- if( !m ) break;
- z *= z;
- }
- if(retRecY){
- y = DReciprocal(y); // 1/y
- }
- return y;
- }
sdfdpow.cpp : last modifiled at 2015/12/03 21:38:14(2,326 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).